﻿using ClusteringProblem.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClusteringProblem.Maths.QualityMeasures
{
    /// <summary>
    /// Współczynnik Rand
    /// 
    /// (a + b) / (n * (n - 1) / 2)
    /// </summary>
    public class RandCoefficient : QualityMeasureStrategy
    {
        /// <summary>
        /// Obliczenie współczynnika Rand
        /// </summary>
        /// <param name="result">podział będący rezultatem algorytmu grupowania</param>
        /// <param name="source">podział źródłowy</param>
        /// <returns>wartość z przedziału [0, 1]</returns>
        public override double Compute(List<IAntType> result, List<Model.Object> source)
        {
            int n = result.Count;
            int a = CountPairs(result, source, true, true);
            int b = CountPairs(result, source, false, true);

            return (double)(a + b) / (n * (n - 1) / 2.0);
        }

        /// <summary>
        /// Zliczenie par
        /// </summary>
        /// <param name="result"></param>
        /// <param name="source"></param>
        /// <param name="theSame"></param>
        /// <param name="reverse"></param>
        /// <returns></returns>
        private int CountPairs(List<IAntType> result, List<Model.Object> source, bool theSame, bool reverse)
        {
            // złączenie 2 list w 1 po ID-kach
            var joined = (from c in result
                          join d in source on c.ObjectID equals d.ID.ToString()
                          select new { ID = d.ID, ResultGroup = c.ResultGroupID, SourceGroup = d.GroupID }).ToList();

            int counter = 0;

            for (int i = 0; i < joined.Count; ++i)
                for (int j = 0; j < i; ++j)
                    if (reverse)
                    {
                        if ((joined[i].ResultGroup == joined[j].SourceGroup == theSame) &&
                           (joined[j].ResultGroup == joined[i].SourceGroup == theSame))
                            counter++;
                    }
                    else
                        if ((joined[i].ResultGroup != joined[j].SourceGroup == theSame) &&
                           (joined[j].ResultGroup == joined[i].SourceGroup == theSame))
                            counter++;

            return counter;
        }             
    }
}
